﻿using System;
using System.Linq.Expressions;
using ProLinq.Toolkit.Expressions;

namespace ProLinq.Projection.Configuration.Fluent
{
	public static class FluentExtensions
	{
		#region ProjectionConfiguration

		public static ProjectionConfiguration EnableOptimization(this ProjectionConfiguration config, Boolean enable = true)
		{
			config.EnableOptimization = enable;
			return config;
		}

		public static ProjectionConfiguration EnablePartialProjection(this ProjectionConfiguration config,
		                                                              Boolean enable = true)
		{
			config.EnablePartialProjection = enable;
			return config;
		}

		public static ProjectionConfiguration ForceAnonymousProjection(this ProjectionConfiguration config,
		                                                               Boolean force = true)
		{
			config.ForceAnonymousProjection = force;
			return config;
		}

		public static ProjectionConfiguration AddProjection<TSource, TResult>(this ProjectionConfiguration config,
		                                                                      Action<Projection<TSource, TResult>> configure)
		{
			var projection = new Projection<TSource, TResult>();
			config.Projections.Add(projection);
			configure(projection);
			return config;
		}

		#endregion

		#region Projection

		public static Projection UseFactory(this Projection config, Delegate factory)
		{
			config.Factory = factory;
			return config;
		}

		public static Projection<TSource, TResult> UseFactory<TSource, TResult>(this Projection<TSource, TResult> config, Func<TSource, TResult> factory)
		{
			config.Factory = factory;
			return config;
		}

		public static Projection<TSource, TResult> Map<TSource, TResult>(this Projection<TSource, TResult> config,
		                                                                 Expression<Func<TSource, Object>> sourceMember,
		                                                                 Expression<Func<TResult, Object>> resultMember)
		{
			var sourceProp = sourceMember.GetMemberInfo();
			var resultProp = resultMember.GetMemberInfo();

			config.Map.Add(new PropertyMap(sourceProp, resultProp));

			return config;
		}

		#endregion

	}
}
